# -*- coding: utf8 -*-

__author__ = 'sergey'

import gobject
from datetime import datetime
from threading import Thread, Event
from time import sleep

class FindDupFiles(Thread):
    """
    __init__ : args = ( app, ui, db_req, stats_req )
    """

    app = None
    ui = None
    db_req = None
    stats_req = None

    stop_event = None

    done_event = None

    log = None

    def __init__(self, group=None, target=None, name=None,
                 args=(), kwargs=None, verbose=None):
        self.app, self.ui, self.db_req, self.stats_req = args
        Thread.__init__(self, group, target, name, args, kwargs, verbose)

    def run(self):
        from logger import get_file_logger
        self.log = get_file_logger("worker-FindDupFiles")
        self.stop_event = Event()
        self.done_event = Event()
        try:
            self.find_dupfiles()
        except Exception as e:
            self.log.error(e)

        self.db_req.close()
        return 0


    def get_nonuniq_files(self):
        """
        @return: [ { "file":<File>, "hash":<Hash> },.. ]
        @rtype: list
        """

        # this = "FindDupFiles::get_nonuniq_files"

        hash_ids = self.db_req.get_nonuniq_hash_ids()

        #self.log.debug("%s: hash_ids=%r" % (this, hash_ids,))

        file_hash = self.db_req.get_file2hash_by_hash_ids(hash_ids)

        #self.log.debug("%s: file_hash=%r" % (this, file_hash,))

        result = []
        if len(file_hash):

            files = self.db_req.get_files_by_ids(tuple(file_hash.keys()))

            hashes = self.db_req.get_hashes_by_ids(tuple(file_hash.values()))

            #self.log.debug("%s: files=%r" % (this, files,))
            #self.log.debug("%s: hashes=%r" % (this, hashes,))

            for item in files:

                hash_id = file_hash[ str(item["id"]) ]

                for shash in hashes:
                    if str(shash["id"]) == hash_id:
                        result.append({
                            "file":item,
                            "hash":shash
                        })
                        break

        return result


    def update_ui(self, event):
        def _timer_call():
            self.app.update_ui_stats()
            if event.isSet():
                stats = self.stats_req.get_update()

                nuq_sz, nuq_un = self.app.format_file_size_si( stats["nonunique_size"] )
                nuqn_sz, nuqn_un = self.app.format_file_size_si( stats["nonunique_size_now"] )

                gobject.idle_add( self.ui.get_object("progressbar_nonuniq").set_fraction, 1.0 )
                gobject.idle_add( self.ui.get_object("progressbar_nonuniq").set_text,
                                  "Сейчас: %d (%0.3f%s); Найдено: %d (%0.3f%s)" % (
                                      stats["nonunique_count_now"], nuqn_sz, nuqn_un,
                                      stats["nonunique_count"], nuq_sz, nuq_un,
                                  )
                )
                event.clear()

            return not event.isSet()
        return _timer_call


    def find_dupfiles(self):

        self.log.info("START")

        treeview3 = self.ui.get_object("treeview3")
        store = treeview3.get_model()

        store.clear()

        files_and_hashes = self.get_nonuniq_files()

        #self.log.debug("Duplicate files and hashes:")
        #self.log.debug(files_and_hashes)

        gobject.timeout_add( 200, self.update_ui(self.done_event) )

        stats = self.stats_req.get_update()

        update = False
        if not stats["nonunique_size"]:
            update = True

        for item in files_and_hashes:

            if self.stop_event.isSet():
                break

            fitem = item["file"]
            hitem = item["hash"]

            hash_id_str = str(hitem["id"])

            hiter = self.app.search( store, store.iter_children(None), self.app.match_func, (0, hash_id_str,) )

            if not hiter:
                hiter = store.append( None, [ hash_id_str, None, None, None, None, None, None, None, 0, 0, 0 ] )

            fiter = self.app.search( store, store.iter_children(None), self.app.match_func, (1, str(fitem["id"]),) )

            if not fiter:
                md = datetime.fromtimestamp( fitem["mtime"] )
                f_s, f_u = self.app.format_file_size_si( fitem["size"] )
                store.append( hiter, [
                    None,
                    fitem["id"],
                    self.app.idle_button_del_file_clicked,
                    md.strftime("%Y-%m-%d %H:%M:%S"),
                    "%0.3f %s" % (f_s, f_u,),
                    fitem["mime"],
                    self.db_req.get_file_full_path( fitem ),
                    "Удалить", 2, 2, fitem["size"] ] )

                if update:
                    self.stats_req.inc("nonunique_count", 1)
                    self.stats_req.inc("nonunique_size", fitem["size"])
                    self.stats_req.inc("nonunique_count_now", 1)
                    self.stats_req.inc("nonunique_size_now", fitem["size"])

        self.log.info("-- all done")
        self.done_event.set()
        self.log.info("-- wait timer stop")
        self.done_event.wait()
        self.log.info("-- timer stopped")

        if not self.stop_event.isSet():
            self.ui.get_object("button_find_dupfiles").set_active(False)

        self.stop_event.clear()

        self.log.info("STOP")

        return
